package com.usian.admin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.usian.admin.feign.ApArticleFeign;
import com.usian.admin.feign.WmNewsFeign;
import com.usian.admin.service.AdChannelService;
import com.usian.admin.service.AdSensitiveService;
import com.usian.admin.service.WemediaNewsAutoScanService;
import com.usian.common.aliyunutils.GreenImageScan;
import com.usian.common.aliyunutils.GreenTextScan;
import com.usian.common.fastDFS.FastDFSClient;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.admin.pojos.AdChannel;
import com.usian.model.article.pojos.ApArticle;
import com.usian.model.article.pojos.ApArticleConfig;
import com.usian.model.article.pojos.ApArticleContent;
import com.usian.model.article.pojos.ApAuthor;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.dtos.WmNewsVo;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmUser;
import com.usian.utils.common.SensitiveWordUtil;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.log4j.Log4j2;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;

@Service
@Log4j2
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {

    @Autowired
    private WmNewsFeign wmNewsFeign;

    @Autowired
    private ApArticleFeign apArticleFeign;

    @Autowired
    private GreenTextScan greenTextScan;

    @Autowired
    private GreenImageScan greenImageScan;

    @Autowired
    private FastDFSClient fastDFSClient;

    @Autowired
    private AdSensitiveService adSensitiveService;

    @Autowired
    private AdChannelService adChannelService;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Value("${fileServerUrl}")
    private String host;

    @GlobalTransactional
    @Override/*文章自动审核*/
    public void autoScanByMediaNewsId(Integer id) {

        try {
            /*校验参数*/
            if (id==null){
                log.error("审核Id为空");
            }

            /*根据id查询需要审核的自媒体文章*/
            WmNews wmNews = wmNewsFeign.findNewsById(id);
            if (wmNews == null) {
                log.error("审核的自媒体文章不存在，自媒体的id:{}", id);
                return;
            }

            /*人工审核通过*/
            if (wmNews.getStatus()==4){
                /*人工审核通过*/
                this.saveArticle(wmNews);
                return;
            }

            /*待发布*/
            if (wmNews.getStatus()==8){
                /*传过来的状态为8 */
                this.saveArticle(wmNews);
                return;
            }

            /*判断审核状态   待审核1*/
            if (wmNews.getStatus()==1){
                Map<String, Object> contentMap = this.handleTextAndImages(wmNews);

                /*审核文本*/
                Map textMap = greenTextScan.greeTextScan(contentMap.get("text").toString());
                /*pass 是通过(未命中) block 是未通过(命中) review 不确定*/
                if (!textMap.get("suggestion").equals("pass")){
                    /*审核失败 状态为2*/
                    if (textMap.get("suggestion").equals("block")){
                        updateWmNews(wmNews,(short)2,"阿里云内容审核不通过");
                        return;
                    }
                    /*人工审核 状态为3*/
                    if (textMap.get("suggestion").equals("review")){
                        updateWmNews(wmNews,(short)3,"阿里云内容审核不确定交给人工审核");
                return;
                    }
                }

                /*审核图片 里面有内容图片也有封面图片*/
                List<String > imageList = (List<String>) contentMap.get("image");

                /*用户审核图片的集合*/
                List<byte[]> byteList = new ArrayList<>();

                /*s表示全路径(域名＋组名＋路径)*/
                for (String s : imageList) {
                    String replace = s.replace(host, "");
                    int index = replace.indexOf("/");
                    String imageName = replace.substring(0, index);
                    String imagePath = replace.substring(index + 1);
                    byte[] bytes = fastDFSClient.download(imageName, imagePath);
                    byteList.add(bytes);
                }

                Map imageMap = greenImageScan.imageScan(byteList);

                /*pass 是通过(未命中) block 是未通过(命中) review 不确定*/
                if (!textMap.get("suggestion").equals("pass")){
                    /*审核失败 状态为2*/
                    if (textMap.get("suggestion").equals("block")){
                        updateWmNews(wmNews,(short)2,"阿里云图片审核不通过");
                return;
                    }
                    /*人工审核 状态为3*/
                    if (textMap.get("suggestion").equals("review")){
                        updateWmNews(wmNews,(short)3,"阿里云图片审核不确定交给人工审核");
                return;
                    }
                }

                /*审核敏感词*/
                List<String> sensitive = adSensitiveService.findAllSensitive();
                /*DFA算法 过滤敏感词*/
                SensitiveWordUtil.initMap(sensitive);
                Map<String, Integer> word = SensitiveWordUtil.matchWords(contentMap.get("text").toString());
                if (word.size()>0){
                    this.updateWmNews(wmNews,(short) 2,"文本敏感词审核不通过");
                    return;
                }


                /*保存ap端相关的表都通过了更新状态为9 已发布*/
                this.saveArticle(wmNews);
                return;

            }

            /*如果传过来的status不是1也不是4也不是8 应该得修改状态为3 让人工来审核*/

            this.updateWmNews(wmNews,(short) 3,"传过来的状态不确定让人工来审核");


        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override/*根据文章标题分页查询自媒体文章列表*/
    public PageResponseResult findNews(NewsAuthDto dto) {
        //分页查询
        PageResponseResult responseResult =  wmNewsFeign.findList(dto);
        //有图片需要显示，需要fasfdfs服务器地址
        responseResult.setHost(host);
        return responseResult;
    }

    @Override/*根据文章id文章信息*/
    public ResponseResult findOne(Integer id) {
        //1参数检查
        if(id == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2查询数据
        WmNewsVo wmNewsVo = wmNewsFeign.findWmNewsVo(id);
        //结构封装
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        responseResult.setHost(host);
        return responseResult;
    }

    @Override/*审核通过或驳回*/
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        //1.参数检查
        if(dto == null || dto.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        //2.查询文章
        WmNews wmNews = wmNewsFeign.findNewsById(dto.getId());
        if(wmNews == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //3.审核没有通过
        if(type.equals(0)){
            updateWmNews(wmNews,(short)2,dto.getMsg());
        }else if(type.equals(1)){
            //4.人工审核通过
            updateWmNews(wmNews,(short)4,"人工审核通过");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /*保存ap端文章表*/
    private void saveArticle(WmNews wmNews){

        ApArticle article = apArticleFeign.findArticleById(wmNews.getArticleId());

        Long id = wmNews.getArticleId();

        if (article==null) {

            /*先保存主表*/
            ApArticle apArticle = new ApArticle();
            apArticle.setTitle(wmNews.getTitle());
            apArticle.setLayout(wmNews.getType());
            apArticle.setImages(wmNews.getImages());
            apArticle.setCreatedTime(new Date());
            apArticle.setPublishTime(new Date());

            /*根据自媒体文章userId查询自媒体用户表*/
            WmUser wmUser = wmNewsFeign.findWmUserById(wmNews.getUserId().longValue());
            if (wmUser != null) {
                ApAuthor apAuthor = apArticleFeign.findByName(wmUser.getName());
                if (apAuthor != null) {
                    apArticle.setAuthorId(apAuthor.getId().longValue());
                    apArticle.setAuthorName(apAuthor.getName());
                }
            }

            /*根据自媒体文章表的channelId查询频道*/
            AdChannel adChannel = adChannelService.getOne(Wrappers.<AdChannel>lambdaQuery().eq(AdChannel::getId, wmNews.getChannelId()));
            if (adChannel != null) {
                apArticle.setChannelId(adChannel.getId());
                apArticle.setChannelName(adChannel.getName());
            }

            /*保存ap端文章表*/
            article= apArticleFeign.saveArticle(apArticle);

            id = article.getId();

            /*保存完ap端文章表的时候,返回主键  给自媒体的article_id 赋值 主要是用于自媒体文章上下架(enable)的时候  需要同步ap端文章配置表的(is_down)*/
            wmNews.setArticleId(id);
            wmNewsFeign.updateWmNews(wmNews);
        }

        ApArticleContent content= apArticleFeign.findContentById(id);
        if (content==null) {
            /*保存ap端内容表*/
            ApArticleContent apArticleContent = new ApArticleContent();
            apArticleContent.setArticleId(id);
            apArticleContent.setContent(wmNews.getContent());
            apArticleFeign.saveArticleContent(apArticleContent);
        }
        ApArticleConfig config = apArticleFeign.findConfigById(id);
        if (config==null) {
            /*保存ap端配置表*/
            ApArticleConfig apArticleConfig = new ApArticleConfig();
            apArticleConfig.setArticleId(id);
            apArticleConfig.setIsForward(true);
            apArticleConfig.setIsDelete(false);
            apArticleConfig.setIsDown(true);
            apArticleConfig.setIsComment(true);
            apArticleFeign.saveArticleConfig(apArticleConfig);
        }
        if(wmNews.getPublishTime().getTime()<=System.currentTimeMillis()){

            this.updateWmNews(wmNews,(short) 9,"已发布");

            Map<String,Object> map = new HashMap<>();
            map.put("id",article.getId().toString());
            map.put("publishTime",article.getPublishTime());
            map.put("layout",article.getLayout());
            map.put("images",article.getImages());
            map.put("authorId",article.getAuthorId());
            map.put("title",article.getTitle());
            map.put("content",wmNews.getContent());
            IndexRequest indexRequest = new IndexRequest("app_info_article").id(article.getId().toString()).source(map);
            try {
                restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }else {
            this.updateWmNews(wmNews,(short) 8,"待发布");
        }


    }

    /*修改自媒体文章状态(审核失败)*/
    private void updateWmNews(WmNews wmNews,short status,String msg){
        wmNews.setStatus(status);
        wmNews.setReason(msg);
        wmNewsFeign.updateWmNews(wmNews);
    }

    /*分离自媒体文章内容字段content里面的文本和图片*/
    private Map<String,Object> handleTextAndImages(WmNews wmNews){

        /*获取内容*/
        String content = wmNews.getContent();

        /*用于存文本*/
        StringBuilder stringBuilder = new StringBuilder();

        /*用于存图片*/
        List<String > imageList =  new ArrayList<>();

        /*将字符串转map*/
        List<Map> contentList = JSON.parseArray(content, Map.class);

        for (Map map : contentList) {
            if (map.get("type").equals("text")){
                stringBuilder.append(map.get("value"));
            }
            if (map.get("type").equals("image")){
                imageList.add((String) map.get("value"));
            }
        }

        /*处理封面图片*/
        if (wmNews.getImages()!=null){
            String[] split = wmNews.getImages().split(",");
            /*Arrays.asList(数组)有弊端  在后续遍历时如果删除集合里面的元素就会报错 因为此对象和原生对象不一样*/
            imageList.addAll(Arrays.asList(split));
        }

        /*封装map*/
        Map<String ,Object> map = new HashMap<>();
        map.put("text",stringBuilder.toString());
        map.put("image",imageList);

        return map;
    }

}
